﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amazon.SimpleDB.Model;
using System.IO;
using System.Diagnostics;
using System.Web;

namespace OnTime
{
    class Reporter
    {
        private static Reporter _instance = null;

        public static Reporter Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Reporter();
                return _instance;
            }
        }

        private Reporter()
        { }

        public void CreateReport(string project, DateTime startTime, DateTime endTime)
        { 
            int startTimeSec = startTime.ToUniversalTime().ToUnixTime();
            int endTimeSec = endTime.ToUniversalTime().ToUnixTime();
            var timeLogs = new List<TimeLog>();

            List<Item> result = AppContext.Database.GetReports(startTimeSec, endTimeSec, project);
            if (result.Count > 0)
            {
                foreach (var item in result)
                {
                    var timeLog = new TimeLog();
                    timeLog.ID = new Guid(item.Name);
                    foreach (var attr in item.Attribute)
                    {
                        switch (attr.Name)
                        { 
                            case "UserId":
                                timeLog.UserId = attr.Value;
                                break;
                            case "Project":
                                timeLog.Project = attr.Value;
                                break;
                            case "StartTime":
                                timeLog.StartTime = Convert.ToInt32(attr.Value).FromUnixTime().ToLocalTime();
                                break;
                            case "EndTime":
                                timeLog.EndTime = Convert.ToInt32(attr.Value).FromUnixTime().ToLocalTime();
                                break;
                            case "Note":
                                if(!attr.Value.IsNullOrWhitespace())
                                    timeLog.Notes.Add(attr.Value);
                                break;
                            default:
                                break;
                        }
                    }
                    timeLogs.Add(timeLog);
                }

                // Generate the array of dates
                string template = Properties.Resources.ReportTemplate;
                var distinctProjects = timeLogs.Distinct(new ProjectComparer());
                var distinctStartDates = timeLogs.Distinct(new StartTimeComparer());

                string arrayOfDates = "[ ";
                foreach (var date in distinctStartDates)
                    arrayOfDates += string.Format("'{0}/{1}/{2}',", date.StartTime.Month, date.StartTime.Day, date.StartTime.Year);
                arrayOfDates = arrayOfDates.Remove(arrayOfDates.Length - 1);
                arrayOfDates += "]";
                template = template.Replace("##ARRAY-OF-DATES##", arrayOfDates);


                // Generate the series array
                string seriesOfObjects = "series:[ ";
                foreach (var distProject in distinctProjects)
                {
                    seriesOfObjects += string.Format("{{ name: '{0}', data: [ ", distProject.Project);
                    foreach (var distStartDate in distinctStartDates)
                    {
                        // Get all the notes for that project for that day
                        string notesForDay = string.Empty;
                        timeLogs.ForEach(new Action<TimeLog>(tl =>
                        {
                            if (tl.StartTime.Date == distStartDate.StartTime.Date && tl.Project == distProject.Project)
                            {
                                tl.Notes.ForEach(new Action<string>(log => notesForDay += string.Format("{0} ", log)));
                            }
                        }));
                        notesForDay = notesForDay.Replace("\r\n", " ");
                        notesForDay = notesForDay.Replace("'", "&#39;");
                        notesForDay = notesForDay.Replace("\"", "&#34;");
                        // Get the total minutes worked for that day for that project
                        int secondsForDay = 0;
                        timeLogs.ForEach(new Action<TimeLog>(tl =>
                        {
                            if (tl.StartTime.Date == distStartDate.StartTime.Date && tl.Project == distProject.Project)
                            {
                                int secDiff = tl.EndTime.ToUnixTime() - tl.StartTime.ToUnixTime();
                                secondsForDay += secDiff;
                            }
                        }));

                        seriesOfObjects += string.Format("{{ notes: '{0}', y: {1} }},",
                            notesForDay, Math.Round((double)(secondsForDay / 60.0), 2));
                    }
                    seriesOfObjects = seriesOfObjects.Remove(seriesOfObjects.Length - 1);
                    seriesOfObjects += "]},";
                }
                seriesOfObjects = seriesOfObjects.Remove(seriesOfObjects.Length - 1);
                seriesOfObjects += "]";

                template = template.Replace("##SERIES-OBJECT##", seriesOfObjects);
                File.WriteAllText("OnTimeReport.html", template);
                Process.Start("OnTimeReport.html");
            }
        }
    }
}
